package sk.ownage.p1.featurestore;

import java.io.File;
import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.util.ArrayList;
import java.util.List;

import android.os.Environment;
import android.util.Log;

public class TrackStore{
	public static final int DIRECTORY_MAX=256;
	private final String TAG="TrackStore";
	private static TrackStore trackStore=new TrackStore();
	private String rootPath=Environment.getExternalStorageDirectory()+"/featureStore/tracks";
	private static String actualTrackStoreName="";
	private static final String trackStoresPath=Environment.getExternalStorageDirectory()+"/featureStore/trackStores";
	private File rootFolder;
	
	private TrackStore() {
		rootFolder=new File(rootPath);
		if(Environment.getExternalStorageDirectory().canWrite())
			if(!rootFolder.exists()){
				rootFolder.mkdirs();
			}
	}
	
	private TrackStore(String name){
		rootFolder=new File(trackStoresPath+"/"+name);
		if(Environment.getExternalStorageDirectory().canWrite())
			if(!rootFolder.exists()){
				rootFolder.mkdirs();
			}
		actualTrackStoreName=name;
	}
	
	public static TrackStore getInstance() {
		return trackStore;
	}
	
	public static void createTrackStore(String name){
		List<String> existingTrackStores=listTrackStores();
		for (String trackStoreName : existingTrackStores) {
			if(trackStoreName.equals(name))
				return;
		}
		File newLStoreFolder=new File(trackStoresPath+"/"+name);
		newLStoreFolder.mkdirs();
	}
	
	public static TrackStore getInstance(String name){
		List<String> existingTrackStores=listTrackStores();
		for (String trackStoreName : existingTrackStores) {
			if(trackStoreName.equals(name))
				return new TrackStore(name);
		}
		return null;
	}
	
	public static List<String> listTrackStores(){
		List<String> result=new ArrayList<String>();
		File[] trackStoresDirectories=new File(trackStoresPath).listFiles();
		if(trackStoresDirectories!=null)
			for (int i = 0; i < trackStoresDirectories.length; i++) {
				if(!trackStoresDirectories[i].isFile()){
					result.add(trackStoresDirectories[i].getName());
				}
			}
		return result;
	} 
	
	public static void deleteTrackStore (String name){
		if(actualTrackStoreName.equals(name))
			return;
		List<String> existingTrackStores=listTrackStores();
		for (String trackStoreName : existingTrackStores) {
			if(trackStoreName.equals(name))
				DeleteDirectoryRecursively(new File(trackStoresPath+"/"+name));
		}
	}
	
	public Track newTrack(){
		return new Track();
	}
	
	/* return list of all tracks in directory*/
	public List<Track> getTracks(){
		return getFilteredTracks("","");
	}

	/*return list of all tracks in this LandmarkStore directory with same activity*/
	public List<Track> getTracks(String activity){
		return getFilteredTracks(activity,"");
	}
	
	/*return list of all tracks in this LandmarkStore directory with same activity and name*/
	public List<Track> getTracks(String activity,String name){
		return getFilteredTracks(activity,name);
	}
	
	private List<Track> getFilteredTracks(String activity,String name){
		List<Track> result=new ArrayList<Track>();
		File tracksFolder= new File(trackStoresPath+"/"+actualTrackStoreName+"/tracks");
		if(!tracksFolder.exists())
			tracksFolder.mkdirs();
		//File[] tracksDirectories=rootFolder.listFiles();
		File[] tracksDirectories=tracksFolder.listFiles();
		for (int i = 0; i < tracksDirectories.length; i++) {
			if(!tracksDirectories[i].isFile()){
				File[] tracks=tracksDirectories[i].listFiles();
				int folderId=Integer.parseInt(tracksDirectories[i].getName())*DIRECTORY_MAX;
				for (int j = 0; j < tracks.length; j++) {
					String[] trackFileName=tracks[j].getName().split("\\.");
					int trackId=Integer.parseInt(trackFileName[0]);
					int Id=folderId + trackId;
					Log.d(TAG,"id je "+Id);
					if(activity!=""){
						TrackReader tr= new TrackReader(Id,trackStoresPath+"/"+actualTrackStoreName+"/tracks");
						try {
							if(name!=""){
								if(tr.readName().equals(name) && tr.readActivity().equals(activity))
									result.add(new Track(Id,trackStoresPath+"/"+actualTrackStoreName));
							}else{
								tr.readName();
								if(tr.readActivity().equals(activity))
									result.add(new Track(Id,trackStoresPath+"/"+actualTrackStoreName));
							}
							tr.stopReader();
						} catch (Exception e) {
							Log.d(TAG,e.toString());
						}
					}else{
						result.add(new Track(Id,trackStoresPath+"/"+actualTrackStoreName));
					}
				}
			}
		}
		return (result.size()>0)?result:null;
	}

	/* delete track*/
	public boolean deleteTrack(Track track) throws Exception{
		int folderId = track.getID() / DIRECTORY_MAX;
		int fileId = track.getID() % DIRECTORY_MAX;;
		String folderPath = (((folderId / 100) > 0) ? "" : "0")
				+ (((folderId / 10) > 0) ? "" : "0") + folderId;
		String filePath = (((fileId / 100) > 0) ? "" : "0")
				+ (((fileId / 10) > 0) ? "" : "0") + fileId;
		//File trackToDelete=new File(rootPath+"/"+folderPath+"/"+filePath+".bin");
		File trackToDelete=new File(trackStoresPath+"/"+actualTrackStoreName+"/tracks"+"/"+folderPath+"/"+filePath+".bin");
		if(track.getID()==loadMaxId()+1)
			throw new Exception("You cannot delete track that you are actualy recording!");
		if(!trackToDelete.exists())
			throw new Exception("Track not exists!");
		DeleteDirectoryRecursively(new File(trackStoresPath+"/"+actualTrackStoreName+"/geometry"+"/"+folderPath+"/"+filePath));
		return trackToDelete.delete();
	}
	
	private int loadMaxId(){
		//File maxIdpath=new File(rootPath+"/"+"maxId.bin");
		File maxIdpath=new File(trackStoresPath+"/"+actualTrackStoreName+"/tracks"+"/maxId.bin");
		int result=-1;
		if(maxIdpath.exists())
		try {
			FileInputStream fis = new FileInputStream(maxIdpath);
			ObjectInputStream is = new ObjectInputStream(fis);
			result=is.readInt();
			is.close();
		} catch (Exception e) {
			Log.d(TAG, e.toString());
		}
		return result;
	}
	
	private static void DeleteDirectoryRecursively(File fileOrDirectory) {
	    if (fileOrDirectory.isDirectory())
	        for (File child : fileOrDirectory.listFiles())
	            DeleteDirectoryRecursively(child);
	        fileOrDirectory.delete();
	}
	
}
